package pbft

import (
	"blockchain/public/entity"
	"blockchain/public/function"
	"encoding/json"
	"time"
)

type pre_prepareMessage struct {
	priSeq int
	sign string
	trades [TradeSize]entity.Trade
	view int
	sequence int
}

func pre_prepare(priSeq int){
	var trades [TradeSize]entity.Trade
	var pre_prepare pre_prepareMessage
	pre_prepare.view=View
	pre_prepare.sequence=currentTradeSeq
	pre_prepare.priSeq=priSeq
	t:=requestData(priSeq)
	t=orderTrades(t)
	if t!=trades{
		trades=t
		pre_prepare.trades=trades
		data,_:=json.Marshal(pre_prepare.trades)
		pre_prepare.sign=function.Sign(data,pre_prepare.priSeq)
		var flagPre_prepared =make(chan bool)
		go priSendPre_prepare(pre_prepare,flagPre_prepared)
		<-flagPre_prepared
		//fmt.Println(pre_prepare.sign)
	}
}

func priSendPre_prepare(pre_prepare pre_prepareMessage,flagPre_prepared chan bool){
	for i:=0;i<N;i++{
		select {
		case chanRecPre_prepare[i]<-pre_prepare:close(chanRecPre_prepare[i])
		default:
		}
	}
	flagPre_prepared<-true
	close(flagPre_prepared)
}

func orderTrades(t [TradeSize]entity.Trade)[TradeSize]entity.Trade{//得到一个并集有序交易集合
	var tradeOrdered [TradeSize] bool
	for i:=0;i<TradeSize;i++{
		tradeOrdered[i]=false
	}
	var t1[TradeSize] entity.Trade
	var tradeInit entity.Trade
	for i:=0;i<TradeSize;i++{
		if t[i].Sender!=""{
			for j:=i+1;j<TradeSize;j++{
				if t[j]==t[i]{
					t[j]=tradeInit
				}
			}
		}
	}

	for j:=0;j<TradeSize;j++{
		min:=time.Now().Add(50*time.Second)
		var minTimeTradeSeq int
		for i:=0;i<TradeSize;i++{
			if t[i].Sender!=""{
				if !(tradeOrdered[i]){
					if t[i].Timestamp.Before(min) {
						min = t[i].Timestamp
						minTimeTradeSeq = i
					}
				}
			}else{
				break
			}
		}
		tradeOrdered[j]=true
		t1[j]=t[minTimeTradeSeq]
	}
	return t
}


func requestData(priSeq int)[TradeSize]entity.Trade {
	var trades [TradeSize]entity.Trade
	request:=<-chanPriRecRequest[priSeq]
	data,_:=json.Marshal(request.tradeSet)
	res:=function.VerifySign(data,request.sign,request.clientSeq)
	if res{
		trades=request.tradeSet
	}
	return trades
}
